// Copyright (C) joyinter
// All rights reserved.
// 
// Author : Jiang Li
// Date   : 2004-6-28

#include "stdafx.h"
#include ".\scrollbar.h"

//##ModelId=44C4B60801F4
class CJoyScrollButton : public CJoyButton
{
public:
	//##ModelId=44C4B60801F6
    virtual void CM_Drag(const CPoint& p);
};

//##ModelId=44C4B60801F6
void CJoyScrollButton::CM_Drag(const CPoint& p)
{
    //__super::CM_Move(p);
    ((CJoyScrollBar*)m_parent)->MoveScroll(p);
}

IMPLEMENT_DYNAMIC(CJoyScrollBar, CJoyWnd)

//##ModelId=44C4B60202F1
CJoyScrollBar::CJoyScrollBar(void)
{
    m_near      = NULL;
    m_far       = NULL;
    m_scroll    = NULL;

    m_vert      = true;
    m_scrollPos = 0.0f;

    m_skinArea  = true;

    m_scrollEvent   = NULL;
    m_eventWnd      = NULL;
}

//##ModelId=44C4B60202F3
CJoyScrollBar::~CJoyScrollBar(void)
{
}

//##ModelId=44C4B60202FE
void CJoyScrollBar::SetScrollEvent(CJoyWnd* eventWnd, PScrollEvent scrollEvent)
{
    m_scrollEvent   = scrollEvent;
    m_eventWnd      = eventWnd;
}

//##ModelId=44C4B6020301
void CJoyScrollBar::UpdateScrollPos(float scrollPos)
{
    if(m_scrollPos == scrollPos)
    {
        return;
    }
    m_scrollPos = scrollPos;
    ValidateScroll();
}

//##ModelId=44C4B60202C0
void CJoyScrollBar::MoveScroll(const CPoint& p)
{
    float scrollPos;
    if(m_vert)
    {
        CRect rScroll = m_scroll->GetArea();
        int nNear   = m_near->GetArea().Height();
        int nFar    = m_far->GetArea().Height();
        int nScroll = rScroll.Height();

        scrollPos = (float)(p.y-nNear)/(m_area.Height() - nNear - nFar - nScroll);
    }
    else
    {
        CRect rScroll = m_scroll->GetArea();
        int nNear   = m_near->GetArea().Width();
        int nFar    = m_far->GetArea().Width();
        int nScroll = rScroll.Width();

        scrollPos = (float)(p.x-nNear)/(m_area.Width() - nNear - nFar - nScroll);
    }
    CM_SetScrollPos(scrollPos);
}

//##ModelId=44C4B60202BF
void CJoyScrollBar::ValidateScroll()
{
    if(m_vert)
    {
        CRect rScroll = m_scroll->GetArea();
        int nNear   = m_near->GetArea().Height();
        int nFar    = m_far->GetArea().Height();
        int nScroll = rScroll.Height();

        int side1   = nNear + (int)((m_area.Height() - nNear - nFar - nScroll)*m_scrollPos);
        m_scroll->SetArea(
            CRect(0, side1, rScroll.Width(), side1+rScroll.Height()));

        m_scroll->m_moveArea.SetRect(0, nNear, 0, m_area.Height()-nFar-nScroll);
    }
    else
    {
        CRect rScroll = m_scroll->GetArea();
        int nNear   = m_near->GetArea().Width();
        int nFar    = m_far->GetArea().Width();
        int nScroll = rScroll.Width();

        int side1   = nNear + (int)((m_area.Width() - nNear - nFar - nScroll)*m_scrollPos);
        m_scroll->SetArea(
            CRect(side1, 0, side1+rScroll.Width(), rScroll.Height()));

        m_scroll->m_moveArea.SetRect(nNear, 0, m_area.Width()-nFar-nScroll, 0);
    }
}

BEGIN_MESSAGE_MAP(CJoyScrollBar, CJoyWnd)
    ON_WM_CREATE()
    ON_WM_SIZE()
END_MESSAGE_MAP()

//##ModelId=44C4B60202D0
void CJoyScrollBar::CM_SideClick(CJoyButton* btn)
{
    if(m_eventWnd == NULL)
    {
        return;
    }
    SCROLLBAR_MESSAGE msg = (btn == m_near) ? SBM_LINE_NEAR : SBM_LINE_FAR;

    float scrollPos = 0.0f;
    (m_eventWnd->*m_scrollEvent)(this, msg, scrollPos);

    if(m_scrollPos == scrollPos)
    {
        return;
    }
    m_scrollPos = scrollPos;
    ValidateScroll();
}

//##ModelId=44C4B60202C2
void CJoyScrollBar::CM_SetScrollPos(float scrollPos)
{
    if(m_scrollPos == scrollPos)
    {
        return;
    }
    m_scrollPos = scrollPos;
    ValidateScroll();
    if(m_eventWnd != NULL)
    {
        scrollPos = m_scrollPos;
        (m_eventWnd->*m_scrollEvent)(this, SBM_SET_POS, scrollPos);
        if(m_scrollPos == scrollPos)
        {
            return;
        }
        m_scrollPos = scrollPos;
        ValidateScroll();
    }
}

//##ModelId=44C4B60202D3
void CJoyScrollBar::CM_PageClick(const CPoint& pt)
{
    if(m_eventWnd == NULL)
    {
        return;
    }
    int nClick, nScroll;
    if(m_vert)
    {
        nClick = pt.y;
        nScroll = m_scroll->GetArea().top;
    }
    else
    {
        nClick = pt.x;
        nScroll = m_scroll->GetArea().left;
    }
    SCROLLBAR_MESSAGE msg = (nClick < nScroll) ? SBM_PAGE_NEAR : SBM_PAGE_FAR;

    float scrollPos = 0.0f;
    (m_eventWnd->*m_scrollEvent)(this, msg, scrollPos);

    if(m_scrollPos == scrollPos)
    {
        return;
    }
    m_scrollPos = scrollPos;
    ValidateScroll();
}

//##ModelId=44C4B60202E3
void CJoyScrollBar::CM_Mouse(MouseMessage msg, const CPoint& pt)
{
    __super::CM_Mouse(msg, pt);

    if(msg == MM_LeftDown)
    {
        CM_PageClick(pt);
    }
}

//##ModelId=44C4B60202E0
void CJoyScrollBar::CM_LoadSkin(CJoyXmlElement* pSkinElem)
{
    __super::CM_LoadSkin(pSkinElem);

    m_vert = pSkinElem->ReadBoolean("vert", true);
    m_near->SetAlign(m_vert ? AT_Top : AT_Left);
    m_far->SetAlign(m_vert ? AT_Bottom : AT_Right);
    if(!m_vert)
    {
        m_near->m_rotate = -90.0f;
        m_far->m_rotate = -90.0f;
        m_scroll->m_rotate = -90.0f;
    }
    m_scrollPos = 0.0f;
    ValidateScroll();
}

//##ModelId=44C4B602030E
int CJoyScrollBar::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CJoyWnd::OnCreate(lpCreateStruct) == -1)
        return -1;

    m_scroll = new CJoyScrollButton();
    m_scroll->m_name = "scroll";
    m_scroll->Create(this, CRect(0, 0, 100, 100));

    m_near = new CJoyButton();
    m_near->m_name = "near";
    m_near->Create(this, CRect(0, 0, 100, 100));
    m_near->SetAlign(m_vert ? AT_Top : AT_Left);
    m_near->SetClickEvent(this, static_cast<CJoyButton::PClickEvent>(CM_SideClick));

    m_far = new CJoyButton();
    m_far->m_name = "far";
    m_far->Create(this, CRect(0, 0, 100, 100));
    m_far->SetAlign(m_vert ? AT_Bottom : AT_Right);
    m_far->SetClickEvent(this, static_cast<CJoyButton::PClickEvent>(CM_SideClick));

    return 0;
}

//##ModelId=44C4B6020311
void CJoyScrollBar::OnSize(UINT nType, int cx, int cy)
{
    CJoyWnd::OnSize(nType, cx, cy);

    ValidateScroll();
}
